# This code may look unusually verbose for Ruby (and it is), but
# it performs some subtle and complex validation of JSON data.
#
# To parse this JSON, add 'dry-struct' and 'dry-types' gems, then do:
#
#   real_result = RealResult.from_json! "{…}"
#   puts real_result.body.team
#
# If from_json! succeeds, the value returned matches the schema.

require 'json'
require 'dry-types'
require 'dry-struct'

module JsonSchema.S0017.Device.RealResult_Module
  module Types
    include Dry.Types(default: :nominal)

    Hash   = Strict::Hash
    String = Strict::String
  end

  # 主体数据
  class Body < Dry::Struct

    # 代表队/代表团/俱乐部
    attribute :team, Types::String

    # 运动员姓名
    attribute :athlete_name, Types::String

    # 运动员号码
    attribute :athlete_bib, Types::String

    # 运动员联系方式
    attribute :athlete_telephone, Types::String

    # A线成绩
    attribute :result_a, Types::String

    # B线成绩
    attribute :result_b, Types::String

    # 排名
    attribute :rank, Types::String

    def self.from_dynamic!(d)
      d = Types::Hash[d]
      new(
        team:              d.fetch("Team"),
        athlete_name:      d.fetch("AthleteName"),
        athlete_bib:       d.fetch("AthleteBib"),
        athlete_telephone: d.fetch("AthleteTelephone"),
        result_a:          d.fetch("ResultA"),
        result_b:          d.fetch("ResultB"),
        rank:              d.fetch("Rank"),
      )
    end

    def self.from_json!(json)
      from_dynamic!(JSON.parse(json))
    end

    def to_dynamic
      {
        "Team"             => team,
        "AthleteName"      => athlete_name,
        "AthleteBib"       => athlete_bib,
        "AthleteTelephone" => athlete_telephone,
        "ResultA"          => result_a,
        "ResultB"          => result_b,
        "Rank"             => rank,
      }
    end

    def to_json(options = nil)
      JSON.generate(to_dynamic, options)
    end
  end

  # 头部数据
  class Head < Dry::Struct

    # 设备Id
    attribute :device_id, Types::String

    # 消息Uuid
    attribute :message_uuid, Types::String

    # 发送消息的时间。格式：yyyy-MM-dd HH:mm:ss.fff 比如：2020-09-02 12:24:09.923
    attribute :timestamp, Types::String

    # 消息类型
    attribute :message_type, Types::String

    def self.from_dynamic!(d)
      d = Types::Hash[d]
      new(
        device_id:    d.fetch("DeviceId"),
        message_uuid: d.fetch("MessageUuid"),
        timestamp:    d.fetch("Timestamp"),
        message_type: d.fetch("MessageType"),
      )
    end

    def self.from_json!(json)
      from_dynamic!(JSON.parse(json))
    end

    def to_dynamic
      {
        "DeviceId"    => device_id,
        "MessageUuid" => message_uuid,
        "Timestamp"   => timestamp,
        "MessageType" => message_type,
      }
    end

    def to_json(options = nil)
      JSON.generate(to_dynamic, options)
    end
  end

  # 实时成绩
  class RealResult < Dry::Struct

    # 头部数据
    attribute :head, Head

    # 主体数据
    attribute :body, Body

    def self.from_dynamic!(d)
      d = Types::Hash[d]
      new(
        head: Head.from_dynamic!(d.fetch("Head")),
        body: Body.from_dynamic!(d.fetch("Body")),
      )
    end

    def self.from_json!(json)
      from_dynamic!(JSON.parse(json))
    end

    def to_dynamic
      {
        "Head" => head.to_dynamic,
        "Body" => body.to_dynamic,
      }
    end

    def to_json(options = nil)
      JSON.generate(to_dynamic, options)
    end
  end
end
